package cn.shiwei.hr.service.impl;


import cn.shiwei.hr.config.HighlightResultMapper;
import cn.shiwei.hr.doc.CourseDoc;
import cn.shiwei.hr.dto.CourseLisSearchtDTO;
import cn.shiwei.hr.repository.CourseElasticsearchRepository;
import cn.shiwei.hr.repository.PageList;
import cn.shiwei.hr.service.ISearchService;
import cn.shiwei.hr.vo.AggPageItmeVO;
import cn.shiwei.hr.vo.AggPageVO;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements ISearchService {

    @Autowired
    private CourseElasticsearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Override
    public void saveCourse(CourseDoc doc) {
        repository.save(doc);
    }

    @Override
    public void deleteCourse(Long id) {
        repository.deleteById(id);
    }

    @Override
    public AggPageVO searchCourse(CourseLisSearchtDTO queryParams) {

        // QueryBuilder builder;
        // SearchQuery
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();


        // 搜索框, 条件查询
        if (!StringUtils.isEmpty(queryParams.getKeyword())) {
            builder.withQuery(boolQuery.must(QueryBuilders.matchQuery("courseName", queryParams.getKeyword())));
        }

        // 分类过滤, 根据分类id  courseTypeId
        if (null != queryParams.getCourseTypeId()){
            builder.withQuery(boolQuery.filter(QueryBuilders.termQuery("courseTypeId", queryParams.getCourseTypeId())));
        }

        // 根据等级名称 gradeName
        if (!StringUtils.isEmpty(queryParams.getGradeName())){
            builder.withQuery(boolQuery.filter(QueryBuilders.termQuery("gradeName", queryParams.getGradeName())));
        }

        // 根据课程机构名称 tenantName
        if (!StringUtils.isEmpty(queryParams.getTenantName())){
            builder.withQuery(boolQuery.filter(QueryBuilders.termQuery("tenantName", queryParams.getTenantName())));
        }

        // 根据最小金额来过滤 priceMin
        if (null != queryParams.getPriceMin()){
            builder.withQuery(boolQuery.filter(QueryBuilders.rangeQuery("price").gte(queryParams.getPriceMin())));
        }

        // 根据最大金额来过滤 priceMin
        if (null != queryParams.getPriceMax()){
            builder.withQuery(boolQuery.filter(QueryBuilders.rangeQuery("price").lte(queryParams.getPriceMax())));
        }

        // 排序, 排序字段 sortField 排序类型 sortType
        String field = null;
        String sortType = "desc";
        SortOrder sortOrder = SortOrder.DESC;
        if (!StringUtils.isEmpty(queryParams.getSortField())){
            switch (queryParams.getSortField()){
                case "jg":
                    field = "price";
                    break;
                case "xl":
                    field = "saleCount";
                    break;
                case "pl":
                    field = "commentCount";
                    break;
                case "xp":
                    field = "onlineTime";
                    break;
                default:
                    // 默认人气排序
                    field = "viewCount";
                    break;
            }

            if (!sortOrder.toString().equals(sortType)){
                sortOrder = SortOrder.ASC;
            }
            builder.withSort(SortBuilders.fieldSort(field).order(sortOrder));
        }

        // 聚合操作
        TermsAggregationBuilder gradeNameAgg = AggregationBuilders.terms("gradeNameAgg").field("gradeName");
        TermsAggregationBuilder tenantNameAgg = AggregationBuilders.terms("tenantNameAgg").field("tenantName");
        builder.addAggregation(gradeNameAgg).addAggregation(tenantNameAgg);

        // 高亮操作
        // 关键字
        HighlightBuilder.Field highlightBuilder = new HighlightBuilder.Field("courseName").preTags("<span style='color:red'>").postTags("</span>");
        builder.withHighlightFields(highlightBuilder);

        // 加载条件
        builder.withQuery(boolQuery);
        SearchQuery searchQuery = builder.build();

        // 拿到条件查询数据(选用自定义高亮映射, spring集成的不支持高亮)
        AggregatedPage<CourseDoc> courseDocs = template.queryForPage(searchQuery, CourseDoc.class, highlightResultMapper);

        // 拿到聚合数据
        Map<String, List<AggPageItmeVO>> map = new HashMap<>();
        courseDocs.getAggregations().asMap().entrySet().forEach(entry -> {
            StringTerms buckets = (StringTerms) entry.getValue();
            List<AggPageItmeVO> list = new ArrayList<>();
            buckets.getBuckets().forEach(bucket->{
                AggPageItmeVO aggPageItmeVO = new AggPageItmeVO();
                aggPageItmeVO.setKey(bucket.getKeyAsString());
                aggPageItmeVO.setCount(bucket.getDocCount());
                list.add(aggPageItmeVO);
            });
            map.put(entry.getKey(), list);
        });

        // 组装数据
        PageList<CourseDoc> page = new PageList<>(courseDocs.getTotalElements(), courseDocs.getContent());

        return new AggPageVO(map, page);

    }
}
